﻿using System;
using System.Text;

namespace Smart.Web.Mobile
{
    /// <summary>
    /// 
    /// </summary>
    public enum PictgramTreat
    {
        Convert,
        Erase,
    }

    /// <summary>
    /// 
    /// </summary>
    public abstract class MobileEncoding : Encoding
    {
        private readonly Encoding encoding;
        private readonly PictgramTreat pictgramTreat = PictgramTreat.Convert;

        /// <summary>
        /// 
        /// </summary>
        public Encoding BaseEncoding
        {
            get { return this.encoding; }
        }

        /// <summary>
        /// 
        /// </summary>
        public PictgramTreat PictgramTreat
        {
            get { return this.pictgramTreat; }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="encoding"></param>
        /// <param name="pictgramTreat"></param>
        protected MobileEncoding(Encoding encoding, PictgramTreat pictgramTreat)
        {
            this.encoding = encoding;
            this.pictgramTreat = pictgramTreat;
        }

        //--------------------------------------------------------------------------------//
        // 出力
        //--------------------------------------------------------------------------------//

        /// <summary>
        /// 
        /// </summary>
        /// <param name="chars"></param>
        /// <param name="index"></param>
        /// <param name="count"></param>
        /// <returns></returns>
        public override int GetByteCount(char[] chars, int index, int count)
        {
            // 手抜き
            int size = GetMaxByteCount( count );
            byte[] temp = new byte[size];
            return GetBytes( chars, index, count, temp, 0 );
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="chars"></param>
        /// <param name="charIndex"></param>
        /// <param name="charCount"></param>
        /// <param name="bytes"></param>
        /// <param name="byteIndex"></param>
        /// <returns></returns>
        protected abstract int GetMobileBytes(char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex);

        /// <summary>
        /// 
        /// </summary>
        /// <param name="chars"></param>
        /// <param name="charIndex"></param>
        /// <param name="charCount"></param>
        /// <param name="bytes"></param>
        /// <param name="byteIndex"></param>
        /// <returns></returns>
        public override int GetBytes(char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex)
        {
            // 絵文字削除
            if( this.pictgramTreat == PictgramTreat.Erase )
            {
                char[] temp = new char[ charCount ];

                int dst = 0;
                for( int i = 0; i < charCount; i++ )
                {
                    if( ( chars[ i + charIndex ] < 0xE000 ) || ( chars[ i + charIndex ] >= 0xF900 ) )
                    {
                        temp[ dst ] = chars[ i + charIndex ];
                        dst++;
                    }
                }

                chars = temp;
                charIndex = 0;
                charCount = dst;
            }

            // 固有
            return GetMobileBytes( chars, charIndex, charCount, bytes, byteIndex );
        }

        //--------------------------------------------------------------------------------//
        // 入力
        //--------------------------------------------------------------------------------//

        /// <summary>
        /// 
        /// </summary>
        /// <param name="bytes"></param>
        /// <param name="index"></param>
        /// <param name="count"></param>
        /// <returns></returns>
        public override int GetCharCount(byte[] bytes, int index, int count)
        {
            // 手抜き
            int size = GetMaxCharCount( count );
            char[] temp = new char[ size ];
            return GetChars( bytes, index, count, temp, 0 );
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="bytes"></param>
        /// <param name="byteIndex"></param>
        /// <param name="byteCount"></param>
        /// <param name="chars"></param>
        /// <param name="charIndex"></param>
        /// <returns></returns>
        protected abstract int GetMobileChars(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex);

        /// <summary>
        /// 
        /// </summary>
        /// <param name="bytes"></param>
        /// <param name="byteIndex"></param>
        /// <param name="byteCount"></param>
        /// <param name="chars"></param>
        /// <param name="charIndex"></param>
        /// <returns></returns>
        public override int GetChars(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex)
        {
            // 固有エンコード判定
            int length = GetMobileChars( bytes, byteIndex, byteCount, chars, charIndex );

            // 絵文字削除
            if( this.pictgramTreat == PictgramTreat.Erase )
            {
                int dst = charIndex;
                for( int i = charIndex; i < charIndex + length; i++ )
                {
                    if( ( chars[ i ] < 0xE000 ) || ( chars[ i ] >= 0xF900 ) )
                    {
                        chars[ dst ] = chars[ i ];
                        dst++;
                    }
                }

                length -= charIndex + length - dst;
            }

            return length;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="bytes"></param>
        /// <param name="index"></param>
        /// <param name="count"></param>
        /// <returns></returns>
        public override char[] GetChars(byte[] bytes, int index, int count)
        {
            if( this.pictgramTreat == PictgramTreat.Erase )
            {
                char[] temp = new char[ GetMaxCharCount( count ) ];
                int length = GetChars( bytes, index, count, temp, 0 ); 
                char[] result = new char[ length ];
                Array.Copy( temp, 0, result, 0, length );
                return result;
            }
            else
            {
                return base.GetChars( bytes, index, count );
            }
        }

        //--------------------------------------------------------------------------------//
        // 委譲
        //--------------------------------------------------------------------------------//

        #region <委譲>

        /// <summary>
        /// 
        /// </summary>
        /// <param name="charCount"></param>
        /// <returns></returns>
        public override int GetMaxByteCount(int charCount)
        {
            return this.encoding.GetMaxByteCount( charCount );
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="byteCount"></param>
        /// <returns></returns>
        public override int GetMaxCharCount(int byteCount)
        {
            return this.encoding.GetMaxCharCount( byteCount );
        }

        /// <summary>
        /// 
        /// </summary>
        public override string WebName
        {
            get { return this.encoding.WebName; }
        }

        /// <summary>
        /// 
        /// </summary>
        public override string EncodingName
        {
            get { return this.encoding.EncodingName; }
        }

        /// <summary>
        /// 
        /// </summary>
        public override string HeaderName
        {
            get { return this.encoding.HeaderName; }
        }

        /// <summary>
        /// 
        /// </summary>
        public override string BodyName
        {
            get { return this.encoding.BodyName; }
        }

        /// <summary>
        /// 
        /// </summary>
        public override int CodePage
        {
            get { return this.encoding.CodePage; }
        }

        /// <summary>
        /// 
        /// </summary>
        public override int WindowsCodePage
        {
            get { return this.encoding.WindowsCodePage; }
        }

        /// <summary>
        /// 
        /// </summary>
        public override bool IsBrowserDisplay
        {
            get { return this.encoding.IsBrowserDisplay; }
        }

        /// <summary>
        /// 
        /// </summary>
        public override bool IsBrowserSave
        {
            get { return this.encoding.IsBrowserSave; }
        }

        /// <summary>
        /// 
        /// </summary>
        public override bool IsMailNewsDisplay
        {
            get { return this.encoding.IsMailNewsDisplay; }
        }

        /// <summary>
        /// 
        /// </summary>
        public override bool IsMailNewsSave
        {
            get { return this.encoding.IsMailNewsSave; }
        }

        public override bool IsSingleByte
        {
            get { return this.encoding.IsSingleByte; }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public override byte[] GetPreamble()
        {
            return this.encoding.GetPreamble();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="form"></param>
        /// <returns></returns>
        public override bool IsAlwaysNormalized(NormalizationForm form)
        {
            return this.encoding.IsAlwaysNormalized( form );
        }

        #endregion
    }
}